#include "parcours.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char * TAB_TYPE[4] = {"i32","double","i8*","i1"};

int NbType = 3;
int CompReg = 0;
int Lab=0;
char* DefCode=NULL;
char * Error;
char * DecGlobal = "";

char* concatCode(char* s1, char* s2)
{
  if(s1==NULL && s2==NULL)
    {
      return NULL;
    }
  else
    {
      if(s1==NULL)
	return strdup(s2);
      else if(s2==NULL)
	return strdup(s1);
      else
	{
	  char * res = malloc(sizeof(char)*(strlen(s1)+strlen(s2)+1));
	  sprintf(res,"%s%s", s1, s2);
	  return res;
	}
    }
}

int parcoursAddSubMulDivType(struct noeud * n, struct pile_var * PileVar, struct pile_fonc * PileFonc)
{
  if(!parcoursType(n->fils[0],PileVar, PileFonc)){return 0;}
  if(!parcoursType(n->fils[1],PileVar, PileFonc)){return 0;}
  if(n->fils[0]->type_var==UNDEF || n->fils[1]->type_var==UNDEF)
    {
      Error = strdup("Type indefini:AddSubMulDiv\n");
      return 0;
    }
  else if((n->fils[0]->type_var!=INT_TYPE && n->fils[0]->type_var!=FLOAT_TYPE) || (n->fils[1]->type_var!=INT_TYPE && n->fils[1]->type_var!=FLOAT_TYPE))
    {
      Error = strdup("Type incompatible:AddSubMulDiv\n");
      return 0;
    }
  else if(n->fils[0]->type_var==INT_TYPE)
    {
      n->type_var=n->fils[1]->type_var;
    }
  else
    {
      n->type_var=n->fils[0]->type_var;
    }
  return 1;
}

int parcoursAndOrType(struct noeud * n, struct pile_var * PileVar, struct pile_fonc * PileFonc)
{
  if(!parcoursType(n->fils[0],PileVar,PileFonc)){return 0;}
  if(!parcoursType(n->fils[1],PileVar,PileFonc)){return 0;}
  if(n->fils[0]->type_var==UNDEF || n->fils[1]->type_var==UNDEF)
    {
      Error = strdup("Type indefini: AND/OR\n");
      return 0;
    }
  else if(n->fils[0]->type_var != BOOL_TYPE || n->fils[1]->type_var != BOOL_TYPE)
    {
      Error = strdup("Mauvais type: AND/OR");
      return 0;
    }
  else
    {
      n->type_var = n->fils[0]->type_var;
    }
  return 1;
}

int parcoursCompType(struct noeud * n, struct pile_var * PileVar, struct pile_fonc * PileFonc)
{
  if(!parcoursType(n->fils[0],PileVar,PileFonc)){return 0;}
  if(!parcoursType(n->fils[1],PileVar,PileFonc)){return 0;}
  if(n->fils[0]->type_var==UNDEF || n->fils[1]->type_var==UNDEF)
    {
      Error = strdup("Type indefini: Comparaison\n");
      return 0;
    }
  else if((n->fils[0]->type_var!=INT_TYPE && n->fils[0]->type_var!=FLOAT_TYPE) || (n->fils[1]->type_var!=INT_TYPE && n->fils[1]->type_var!=FLOAT_TYPE))
    {
      Error = strdup("Type incompatible: Comparaison\n");
      return 0;
    }
  else
    {
      n->type_var=BOOL_TYPE;;
    }
  return 1;
}

int getTypeRet(struct noeud * n)
{
  if(n == NULL)
    {
      return VOID;
    }
  else if(n->type_noeud == RET)
    {
      return n->type_var;
    }
  else
    {
      int ret0 = getTypeRet(n->fils[0]);
      int ret1 = getTypeRet(n->fils[1]); 
      int ret2 = getTypeRet(n->fils[2]); 
      int ret3 = getTypeRet(n->fils[3]); 
      if(ret0 == UNDEF || ret1 == UNDEF || ret2 == UNDEF || ret3 == UNDEF)
	return UNDEF;
      if(ret0 != VOID && ret1 != VOID && ret0 != ret1)
	{
	  return UNDEF;
	}
      else if(ret0 == VOID)
	{
	  ret0 = ret1;
	}

      if(ret2!= VOID && ret3 != VOID && ret2 != ret1)
	{
	  return UNDEF;
	}
      else if(ret2 == VOID)
	{
	  ret2 = ret1;
	}

      
      if(ret0 != VOID && ret2 != VOID && ret0 != ret2)
	{
	  return UNDEF;
	}
      else if(ret0 == VOID)
	{
	  ret0 = ret2;
	}
      return ret0;
    }
}
void parcoursCodeDef(struct noeud * n)
{
  struct noeud * param;
  char s1[2048];
  s1[0]='\0';
  char s2[2048];
  s2[0]='\0';
  parcoursCode(n->fils[1]);
  for(param = n->fils[0]; param != NULL ; param = param->fils[0])
    {
      strcat(strcat(strcat(s2,TAB_TYPE[param->type_var])," "),param->reg);
      if(param->fils[0]!= NULL)
	{
	  strcat(s2,", ");
	}
    }
  sprintf(s1,"define %s @%s(%s){\n%s}\n",TAB_TYPE[n->type_var],n->reg,s2,n->fils[1]->code);
  n->def=strdup(s1);
}

void parcoursTypeDef(struct noeud * n, struct pile_var * PileVar, struct pile_fonc * PileFonc, struct noeud * param,char*reg,char*type_fonc)
{
  int i;
  char s_reg[2048];
  s_reg[0]='\0';
  char s_type_fonc[2048];
  s_type_fonc[0]='\0';
  if(param!=NULL)
    {
      for(i=0;i<NbType;i++)
	{
	  empilerSent(PileVar);
	  ajouterVar(PileVar,param->id);
	  setVarType(PileVar,param->id,i);
	  setVarArg(PileVar,param->id);

	  param->type_var = typeVar(PileVar,param->id);
	  param->reg= strdup(regVar(PileVar,param->id));

	  strcpy(s_reg,reg);
	  strcat(s_reg,"_");
	  strcat(s_reg,TAB_TYPE[i]);

	  if(type_fonc == NULL)
	    {
	      strcpy(s_type_fonc,TAB_TYPE[i]);
	    }
	  else
	    {
	      strcpy(s_type_fonc,type_fonc);
	      strcat(s_type_fonc,", ");
	      strcat(s_type_fonc,TAB_TYPE[i]);
	    }

	  parcoursTypeDef(n,PileVar,PileFonc,param->fils[0],s_reg,s_type_fonc);
	  depiler(PileVar);
	}
    }
  else if(parcoursType(n->fils[1],PileVar,PileFonc))
    {
      int ret=getTypeRet(n->fils[1]);
      if(ret!=UNDEF)
	{
	  n->type_var=ret;
	  n->reg=strdup(reg);
	  char s[2048];
	  sprintf(s,"%s (%s)*",TAB_TYPE[n->type_var],type_fonc);
	  n->type_fonc=strdup(s);
	  ajouterFonc(PileFonc, n->reg, n->type_fonc, n->type_var);
	  parcoursCodeDef(n);
	  DefCode = concatCode(DefCode,n->def);
	}
    }
}

int parcoursType(struct noeud * n, struct pile_var * PileVar, struct pile_fonc * PileFonc)
{
  char s1[2048];
  if(n!=NULL)
    {
      switch(n->type_noeud)
	{
	case TOPSTMTS:
	  if(!parcoursType(n->fils[0],PileVar,PileFonc)){return 0;}
	  if(!parcoursType(n->fils[1],PileVar,PileFonc)){return 0;}
	  break;
	case CLASS:
	  Error = strdup("Class Non Implementée\n");
	  return 0;	  
	  break;
	case HERIT:
	  Error = strdup("Heritage Non Implementée\n");
	  return 0;	  
	  break;
	case STMTS:
	  if(!parcoursType(n->fils[0],PileVar,PileFonc)){return 0;}
	  if(!parcoursType(n->fils[1],PileVar,PileFonc)){return 0;}
	  break;
	case IF:
	  if(!parcoursType(n->fils[0],PileVar,PileFonc)){return 0;}
	  if(n->fils[0]->type_var!=BOOL_TYPE)
	    {
	      Error = strdup("Type incompatible: If\n");
	      return 0;
	    }
	  empilerSent(PileVar);
	  if(parcoursType(n->fils[1],PileVar,PileFonc))
	    depiler(PileVar);
	  else
	    {
	      depiler(PileVar);
	      return 0;
	    }
	  break;
	case IFELSE:
	  if(!parcoursType(n->fils[0],PileVar,PileFonc)){return 0;}
	  if(n->fils[0]->type_var!=BOOL_TYPE)
	    {
	      Error = strdup("Type incompatible: IfElse\n");
	      return 0;
	    }
	  empilerSent(PileVar);
	  if(parcoursType(n->fils[1],PileVar,PileFonc))
	    depiler(PileVar);
	  else
	    {
	      depiler(PileVar);
	      return 0;
	    }
	  empilerSent(PileVar);
	  if(parcoursType(n->fils[2],PileVar,PileFonc))
	    depiler(PileVar);
	  else
	    {
	      depiler(PileVar);
	      return 0;
	    }
	  break;
	case WHILE:
	  if(!parcoursType(n->fils[0],PileVar,PileFonc)){return 0;}
	  if(n->fils[0]->type_var!=BOOL_TYPE)
	    {
	      Error = strdup("Type incompatible: While\n");
	      return 0;
	    }
	  empilerSent(PileVar);
	  if(!parcoursType(n->fils[1],PileVar,PileFonc)){return 0;}
	  parcoursCode(n->fils[1]);
	  depiler(PileVar);
	  parcoursCode(n->fils[0]);
	  break;
	case AFFECT:
	  if(!parcoursType(n->fils[0],PileVar,PileFonc)){return 0;}
	  if(!parcoursType(n->fils[1],PileVar,PileFonc)){return 0;}
	  if(n->fils[1]->type_var==UNDEF)
	    {
	      Error = strdup("Type indefini: Affectation\n");
	      return 0;
	    }
	  else if(n->fils[0]->type_var==UNDEF)
	    {
	      setVarType(PileVar,n->fils[0]->id,n->fils[1]->type_var);
	      n->fils[0]->type_var=n->fils[1]->type_var;
	    }
	  else if(n->fils[0]->type_var!=n->fils[1]->type_var)
	    {
	      Error = strdup("Type incompatible: Affectation\n");
	      return 0;
	    }
	  break;
	case RET:
	  if(!parcoursType(n->fils[0],PileVar,PileFonc)){return 0;}
	  n->type_var=n->fils[0]->type_var;
	  break;
	case DEF:
	  parcoursTypeDef(n,reInitPileLoc(PileVar),PileFonc,n->fils[0],n->id,NULL);
	  break;
	case ID:
	  if(!existeVar(PileVar,n->id))
	    {
	      ajouterVar(PileVar,n->id);
	      n->allocate = 1;
	    }
	  n->type_var=typeVar(PileVar,n->id);
	  n->reg=strdup(regVar(PileVar,n->id));
	  break;
	case METH:
	  Error = strdup("Methode Non Implementée\n");
	  return 0;	  
	  break;
	case APPEL:
	  if(!parcoursType(n->fils[0],PileVar,PileFonc)){return 0;}
	  s1[0]='\0';
	  strcat(s1,n->id);
	  struct noeud * noeud = n->fils[0];
	  while(noeud->type_noeud==EXPR)
	    {
	      strcat(s1,"_");
	      strcat(s1,TAB_TYPE[noeud->fils[0]->type_var]); 
	      noeud=noeud->fils[1];  
	    }
	  strcat(s1,"_");
	  strcat(s1,TAB_TYPE[noeud->type_var]);
	  if(!existeFonc(PileFonc,s1))
	    {
	      Error = strdup("Fonction indefinie\n");
	      return 0;
	    }
	  else
	    {
	      n->type_fonc=getFoncType(PileFonc,s1);
	      n->type_var=getFoncTypeRet(PileFonc,s1);
	      n->nom = strdup(s1);
	    }
	  break;
	case EXPR:
	  if(!parcoursType(n->fils[0],PileVar,PileFonc)){return 0;}
	  if(!parcoursType(n->fils[1],PileVar,PileFonc)){return 0;}
	  break;
	case STRING:
	  Error = strdup("String Non Implementée\n");
	  return 0;	  
	  break;
	case FLOAT:
	  n->type_var=FLOAT_TYPE;
	  break;
	case INT:
	  n->type_var=INT_TYPE;
	  break;
	case AND:
	  if(!parcoursAndOrType(n,PileVar, PileFonc)){return 0;}
	  break;
	case OR:
	  if(!parcoursAndOrType(n,PileVar, PileFonc)){return 0;}
	  break;
	case SI:
	  if(!parcoursCompType(n,PileVar, PileFonc)){return 0;}
	  break;
	case SS:
	  if(!parcoursCompType(n,PileVar, PileFonc)){return 0;}
	  break;
	case LEQ:
	  if(!parcoursCompType(n,PileVar, PileFonc)){return 0;}
	  break;
	case GEQ:
	  if(!parcoursCompType(n,PileVar, PileFonc)){return 0;}
	  break;
	case EQ:
	  if(!parcoursCompType(n,PileVar, PileFonc)){return 0;}
	  break;
	case NEQ:
	  if(!parcoursCompType(n,PileVar, PileFonc)){return 0;}
	  break;
	case ADD:
	  if(!parcoursAddSubMulDivType(n,PileVar, PileFonc)){return 0;}
	  break;
	case SUB:
	  if(!parcoursAddSubMulDivType(n,PileVar, PileFonc)){return 0;}
	  break;
	case MUL:
	  if(!parcoursAddSubMulDivType(n,PileVar, PileFonc)){return 0;}
	  break;
	case DIV:
	  if(!parcoursAddSubMulDivType(n,PileVar, PileFonc)){return 0;}
	  break;
	case CHARGER:
	  if(!parcoursType(n->fils[0],PileVar, PileFonc)){return 0;}
	  if(n->fils[0]->type_noeud != APPEL)
	    {
	      n->arg=estVarArg(PileVar,n->fils[0]->id);
	    }
	  n->type_var=n->fils[0]->type_var;
	  break;
	}
    }
  return 1;
}

void parcoursCodeAndOr(struct noeud * n, char * signe)
{
  char r1[2048];
  char s[2048];
  parcoursCode(n->fils[0]);
  parcoursCode(n->fils[1]);
  sprintf(r1,"%%r%d",CompReg);
  CompReg++;
  n->reg=strdup(r1);
  sprintf(s,"%s = %s %s %s, %s\n",r1,signe,TAB_TYPE[n->fils[0]->type_var],n->fils[0]->reg,n->fils[1]->reg);
  n->code=concatCode(concatCode(n->fils[0]->code,n->fils[1]->code),s);
}

void parcoursCodeCompInt(struct noeud * n, char * signe)
{
  char r1[2048];
  char s[2048];
  parcoursCode(n->fils[0]);
  parcoursCode(n->fils[1]);
  sprintf(r1,"%%r%d",CompReg);
  CompReg++;
  n->reg=strdup(r1);
  sprintf(s,"%s = icmp %s %s %s, %s\n",r1,signe,TAB_TYPE[n->fils[0]->type_var],n->fils[0]->reg,n->fils[1]->reg);
  n->code=concatCode(concatCode(n->fils[0]->code,n->fils[1]->code),s);
}

void parcoursCodeCompFloat(struct noeud * n, char * signe)
{
  char r1[2048];
  char r2[2048];
  char s1[2048];
  char s2[2048];
  parcoursCode(n->fils[0]);
  parcoursCode(n->fils[1]);
  
  if(n->fils[0]->type_var == INT_TYPE)
    {
      sprintf(r1,"%%r%d",CompReg);
      CompReg++;
      sprintf(s1,"%s = sitofp %s %s to %s\n",r1,TAB_TYPE[INT_TYPE],n->fils[0]->reg,TAB_TYPE[FLOAT_TYPE]);
      sprintf(r2,"%%r%d",CompReg);
      CompReg++;
      sprintf(s2,"%s = fcmp %s %s %s, %s\n",r2,signe,TAB_TYPE[n->fils[1]->type_var],r1,n->fils[1]->reg);
      n->reg=strdup(r2);
      n->code=concatCode(concatCode(concatCode(n->fils[0]->code,n->fils[1]->code),s1),s2);
    }
  else if(n->fils[1]->type_var == INT_TYPE)
    {
      sprintf(r1,"%%r%d",CompReg);
      CompReg++;
      sprintf(s1,"%s = sitofp %s %s to %s\n",r1,TAB_TYPE[INT_TYPE],n->fils[1]->reg,TAB_TYPE[FLOAT_TYPE]);
      sprintf(r2,"%%r%d",CompReg);
      CompReg++;
      sprintf(s2,"%s = fcmp %s %s %s, %s\n",r2,signe,TAB_TYPE[n->fils[0]->type_var],n->fils[0]->reg,r1);
      n->reg=strdup(r2);
      n->code=concatCode(concatCode(concatCode(n->fils[0]->code,n->fils[1]->code),s1),s2);
    } 
  else
    {
      sprintf(r1,"%%r%d",CompReg);
      CompReg++;
      sprintf(s1,"%s = fcmp %s %s %s, %s\n",r1,signe,TAB_TYPE[n->fils[0]->type_var],n->fils[0]->reg,n->fils[1]->reg);
      n->reg=strdup(r1);
      n->code=concatCode(concatCode(n->fils[0]->code,n->fils[1]->code),s1);
    }
} 

void parcoursAddSubMulDivCode(struct noeud * n, char* opi, char* opf)
{
  char s1[2048];
  char s2[2048];
  char r1[2048];
  char r2[2048];
  parcoursCode(n->fils[0]);
  parcoursCode(n->fils[1]);
  if(n->type_var == FLOAT_TYPE)
    {
      if(n->fils[0]->type_var==INT_TYPE)
	{
	  sprintf(r1,"%%r%d",CompReg);
	  CompReg++;
	  sprintf(s1,"%s = sitofp %s %s to %s\n",r1,TAB_TYPE[INT_TYPE],n->fils[0]->reg,TAB_TYPE[FLOAT_TYPE]);
	  sprintf(r2,"%%r%d",CompReg);
	  CompReg++;
	  sprintf(s2,"%s = %s %s %s, %s\n", r2, opf,TAB_TYPE[FLOAT_TYPE], r1, n->fils[1]->reg);
	  n->code=concatCode(concatCode(concatCode(n->fils[0]->code,n->fils[1]->code),s1),s2);
	  n->reg=strdup(r2);
	}
      else if(n->fils[1]->type_var==INT_TYPE)
	{
	  sprintf(r1,"%%r%d",CompReg);
	  CompReg++;
	  sprintf(s1,"%s = sitofp %s %s to %s\n",r1,TAB_TYPE[INT_TYPE],n->fils[1]->reg,TAB_TYPE[FLOAT_TYPE]);
	  sprintf(r2,"%%r%d",CompReg);
	  CompReg++;
	  sprintf(s2,"%s = %s %s %s, %s\n", r2, opf,TAB_TYPE[FLOAT_TYPE], n->fils[0]->reg,r1);
	  n->code=concatCode(concatCode(concatCode(n->fils[0]->code,n->fils[1]->code),s1),s2);     
	  n->reg=strdup(r2);
	}
      else
	{
	  sprintf(r1,"%%r%d",CompReg);
	  CompReg++;
	  sprintf(s1,"%s = %s %s %s, %s\n", r1, opf,TAB_TYPE[FLOAT_TYPE], n->fils[0]->reg,n->fils[1]->reg);
	  n->code=concatCode(concatCode(n->fils[0]->code,n->fils[1]->code),s1);     
	  n->reg=strdup(r1);
	} 
    }
  else
    {
      sprintf(r1,"%%r%d",CompReg);
      CompReg++;
      sprintf(s1,"%s = %s %s %s, %s\n", r1, opi,TAB_TYPE[INT_TYPE], n->fils[0]->reg,n->fils[1]->reg);
      n->code=concatCode(concatCode(n->fils[0]->code,n->fils[1]->code),s1);     
      n->reg=strdup(r1);
    }
}

void parcoursCode(struct noeud * n)
{
  char s1[1024];
  s1[0]='\0';
  char s2[1024];
  s2[0]='\0';
  char s3[1024];
  s3[0]='\0';
  char s4[2048];
  s4[0]='\0';
  char s5[2048];
  s5[0]='\0';
  char r1[2048];
  r1[0]='\0';
  if(n!=NULL)
    {
      switch(n->type_noeud)
	{
	case TOPSTMTS:
	  parcoursCode(n->fils[0]);
	  parcoursCode(n->fils[1]);
	  n->code=concatCode(n->fils[0]->code,n->fils[1]->code);
	  break;
	case CLASS:
	  break;
	case HERIT:
	  break;
	case STMTS:
	  parcoursCode(n->fils[0]);
	  parcoursCode(n->fils[1]);
	  if(n->fils[0]!=NULL && n->fils[1]!=NULL)
	    n->code=concatCode(n->fils[0]->code,n->fils[1]->code);
	  else if(n->fils[0]==NULL && n->fils[1]!=NULL && n->fils[1]->code!= NULL)
	    n->code=strdup(n->fils[1]->code);
	  else if(n->fils[1]==NULL && n->fils[0]!=NULL && n->fils[0]->code!= NULL)
	    n->code=strdup(n->fils[0]->code);
	  break;
	case IF:
	  parcoursCode(n->fils[0]);
	  parcoursCode(n->fils[1]);
	  sprintf(s1,"br i1 %s, label %%L%d, label %%L%d \n",n->fils[0]->reg,Lab,Lab+1);
	  sprintf(s2,"L%d:\n",Lab);
	  sprintf(s3,"br label %%L%d\n",Lab+1);
	  sprintf(s4,"L%d:\n",Lab+1);
	  Lab+=2;
	  n->code=concatCode(concatCode(concatCode(concatCode(concatCode(n->fils[0]->code,s1),s2),n->fils[1]->code),s3),s4);
	  break;
	case IFELSE:
	  parcoursCode(n->fils[0]);
	  parcoursCode(n->fils[1]);
	  parcoursCode(n->fils[2]);
	  sprintf(s1,"br i1 %s, label %%L%d, label %%L%d \n",n->fils[0]->reg,Lab,Lab+1);
	  sprintf(s2,"L%d:\n",Lab);
	  sprintf(s3,"br label %%L%d\n",Lab+2);
	  sprintf(s4,"L%d:\n",Lab+2);
	  sprintf(s5,"L%d:\n",Lab+1);
	  n->code=concatCode(concatCode(concatCode(concatCode(concatCode(concatCode(concatCode(concatCode(n->fils[0]->code,s1),s2),n->fils[1]->code),s3),s5),n->fils[2]->code),s3),s4);
	  Lab+=3;
	  break;
	case WHILE:
	  sprintf(s1,"br label %%L%d\nL%d:\n",Lab,Lab);	  
	  sprintf(s2,"br i1 %s, label %%L%d, label %%L%d \n",n->fils[0]->reg,Lab+1,Lab+2);
	  sprintf(s3,"L%d:\n",Lab+1);
	  sprintf(s4,"br label %%L%d\n",Lab);
	  sprintf(s5,"L%d:\n",Lab+2);
	  Lab+=3;
	  n->code=concatCode(concatCode(concatCode(concatCode(concatCode(concatCode(s1,n->fils[0]->code),s2),s3),n->fils[1]->code),s4),s5);
	  break;
	case AFFECT:
	  parcoursCode(n->fils[0]);
	  parcoursCode(n->fils[1]);
	  sprintf(s1,"store %s %s, %s* %s\n", TAB_TYPE[n->fils[1]->type_var], n->fils[1]->reg, TAB_TYPE[n->fils[0]->type_var], n->fils[0]->reg);
	  n->code=concatCode(concatCode(n->fils[0]->code,n->fils[1]->code),s1);
	  break;
	case RET:
	  parcoursCode(n->fils[0]);
	  sprintf(s1,"ret %s %s\n",TAB_TYPE[n->type_var],n->fils[0]->reg);
	  n->code=concatCode(n->fils[0]->code,s1);
	  break;
	case DEF:
	  break;
	case PARAM:
	  break;
	case ID:
	  if(n->allocate == 1)
	    {
	      if(n->reg[0]=='%')
		{
		  sprintf(s1,"%s = alloca  %s \n", n->reg, TAB_TYPE[n->type_var]);
		  n->code=strdup(s1);
		}
	      else
		{
		  sprintf(s1,"%s = global %s 0\n", n->reg, TAB_TYPE[n->type_var]);
		  DecGlobal=concatCode(DecGlobal,s1);
		}
	    }
	  break;
	case METH:
	  break;
	case APPEL:
	  parcoursCode(n->fils[0]);
	  struct noeud * noeud = n->fils[0];
	  while(noeud->type_noeud==EXPR)
	    {
	      strcat(s2,noeud->fils[0]->code);
	      strcat(s1,TAB_TYPE[noeud->fils[0]->type_var]);
	      strcat(s1," ");
	      strcat(s1,noeud->fils[0]->reg);
	      strcat(s1,", ");
	      noeud=noeud->fils[1];
	    }
	  strcat(s2,noeud->code);
	  strcat(s1,TAB_TYPE[noeud->type_var]);
	  strcat(s1," ");
	  strcat(s1,noeud->reg);
	  
	  if(n->type_var!=VOID)
	    {
	      sprintf(r1,"%%r%d",CompReg);
	      CompReg++;
	      n->reg=strdup(r1);
	      sprintf(s3,"%s = call %s @%s(%s)\n", r1, n->type_fonc, n->nom ,s1);
	    }
	  else 
	    {
	      sprintf(s3,"call %s @%s(%s)\n", n->type_fonc, n->nom ,s1);
	    }

	  n->code=concatCode(s2,s3);
	  break;
	case EXPR:
	  parcoursCode(n->fils[0]);
	  parcoursCode(n->fils[1]);
	  break;
	case STRING:
	  break;
	case FLOAT:
	  sprintf(r1,"%%r%d",CompReg);
	  CompReg++;
	  n->reg=strdup(r1);
	  sprintf(s1,"%s = fadd double %f, 0.\n",r1,n->f);
	  n->code=strdup(s1);
	  break;
	case INT:
	  sprintf(r1,"%%r%d",CompReg);
	  CompReg++;
	  n->reg=strdup(r1);
	  sprintf(s1,"%s = add i32 %d, 0\n",r1,n->i);
	  n->code=strdup(s1);
	  break;
	case AND:
	  parcoursCodeAndOr(n, "and");
	  break;
	case OR:
	  parcoursCodeAndOr(n, "or");
	  break;
	case SI:
	  if(n->fils[0]->type_var!=INT_TYPE || n->fils[1]->type_var!=INT_TYPE)
	    parcoursCodeCompFloat(n,"olt");
	  else
	    parcoursCodeCompInt(n,"slt");
	  break;
	case SS:
	  if(n->fils[0]->type_var!=INT_TYPE || n->fils[1]->type_var!=INT_TYPE)
	    parcoursCodeCompFloat(n,"ogt");
	  else
	    parcoursCodeCompInt(n,"sgt");
	  break;
	case LEQ:
	  if(n->fils[0]->type_var!=INT_TYPE || n->fils[1]->type_var!=INT_TYPE)
	    parcoursCodeCompFloat(n,"ole");
	  else
	    parcoursCodeCompInt(n,"sle");
	  break;
	case GEQ:
	  if(n->fils[0]->type_var!=INT_TYPE || n->fils[1]->type_var!=INT_TYPE)
	    parcoursCodeCompFloat(n,"oge");
	  else
	    parcoursCodeCompInt(n,"sge");
	  break;
	case EQ:
	  if(n->fils[0]->type_var!=INT_TYPE || n->fils[1]->type_var!=INT_TYPE)
	    parcoursCodeCompFloat(n,"oeq");
	  else
	    parcoursCodeCompInt(n,"eq");
	  break;
	case NEQ:
	  if(n->fils[0]->type_var!=INT_TYPE || n->fils[1]->type_var!=INT_TYPE)
	    parcoursCodeCompFloat(n,"one");
	  else
	    parcoursCodeCompInt(n,"ne");
	  break;
	case ADD:
	  parcoursAddSubMulDivCode(n,"add","fadd");
	  break;
	case SUB:
	  parcoursAddSubMulDivCode(n,"sub","fsub");
	  break;
	case MUL:
	  parcoursAddSubMulDivCode(n,"mul","fmul");
	  break;
	case DIV:
	  parcoursAddSubMulDivCode(n,"sdiv","fdiv");
	  break;
	case CHARGER:
	  parcoursCode(n->fils[0]);
	  if(n->fils[0]->type_noeud != APPEL &&! n->arg)
	    {
	      sprintf(r1,"%%r%d",CompReg);
	      CompReg++;
	      sprintf(s1,"%s = load %s* %s\n", r1, TAB_TYPE[n->fils[0]->type_var], n->fils[0]->reg);
	      n->code=strdup(s1);
	      n->reg=strdup(r1);
	    }
	  else
	    {
	      n->reg=strdup(n->fils[0]->reg);
	      if(n->fils[0]->type_noeud == APPEL)
		n->code = strdup(n->fils[0]->code);
	    }
	  break;
	}
    }
}


char* creerMain(char* code)
{
  int taille = 500;
  if(code != NULL)
    taille +=strlen(code);
  if(DefCode != NULL)
    taille += strlen(DefCode);
  char * m = malloc(sizeof(char)*taille);
  if(DefCode==NULL)
    {
      sprintf(m,
	      "declare void @print_double(double)\n"
	      "declare void @print_i32(i32)\n"
	      "%s\n"
	      "define i32 @main(){\n%sret i32 0\n}\n"
	      ,DecGlobal  
	      ,code);
    }
  else
    {
    sprintf(m,
	    "declare void @print_double(double)\n"
	    "declare void @print_i32(i32)\n"
	    "%s\n"
	    "%s\n"  
	    "define i32 @main(){\n%sret i32 0\n}\n"
	    ,DecGlobal  
	    ,DefCode
	    ,code);
    }
  return m;
}

void AfficherErreur()
{
  printf("%s",Error);
}
